<template>
  <!-- 自学模式 -->
  <div class="sbodyd">
    <!-- 图谱详情主体区域-->
    <div class="mainboxgj">
      <!-- 修改为不分 -->
      <div class="mainboxleft" v-if="lodings">
        <!-- 分上方区域 -->
        <!-- 顶部标题栏目 -->
        <div class="maintopbox">
          <div class="mainsera">
            <div class="gobackbox">
              <div class="xbannername" @click="goback">关闭</div>
            </div>
            <div
              class="startbox"
              @click="startfn"
              v-if="!startshow && addbsshowlx"
              >开始练习</div
            >
            <div
              class="startbox"
              @click="startfns"
              v-if="startshow && addbsshowlx"
              >退出练习</div
            >
            <div
              class="startbox"
              @click="allclear"
              v-if="startshow && addbsshowlx"
              >清空作答</div
            >
            <div class="startboxs" v-if="addbsshowlx"
              >显示答案
              <el-switch v-model="state.showText" @change="toggleTextButton"
            /></div>
          </div>

          <div class="maintoptitle"></div>
          <div class="maintopright">
            <div class="czmainitem tool" @click="zoomIn">
              <img src="@/images/fd.png" alt="" class="normal" />
              <img src="@/images/fdac.png" alt="" class="active" />
            </div>
            <div class="czmainitem tool" @click="zoomOut">
              <img src="@/images/sx.png" alt="" class="normal" />
              <img src="@/images/sxac.png" alt="" class="active" />
            </div>
            <div class="czmainitem tool" @click="tdflag = true">
              <img src="@/images/td.png" alt="" class="normal" />
              <img src="@/images/tdac.png" alt="" class="active" />
            </div>
            <div class="czmainitem tool" @click="reset">
              <img src="@/images/cz.png" alt="" class="normal" />
              <img src="@/images/czac.png" alt="" class="active" />
            </div>
          </div>
        </div>
        <!-- 分下方区域 -->
        <div class="mainbottombox">
          <!-- 分左侧区域 -->
          <div class="mainbottomboxleft">
            <!-- 搜索区域 -->
            <div class="mainsers" v-if="!addbsshowlx">
              请输入你想要搜索的内容：
              <el-select
                v-model="markingPointsIdxz"
                filterable
                clearable
                :style="{ width: '320px' }"
                placeholder="请输入"
                :filter-method="handleSearch"
                @change="changeselect"
                remote
                :remote-method="handleSearch"
                :loading="false"
              >
                <el-option
                  v-for="item in optionsselect"
                  :key="item.markingPointsId"
                  :label="item.text"
                  :value="item.markingPointsId"
                />
              </el-select>
            </div>
            <!-- 画布区域 -->

            <div
              class="box"
              ref="box"
              id="canvasContainer"
              :style="{
                backgroundColor: atlasTypeName == '插画' ? '#ffff' : 'black',
              }"
            >
              <canvas
                id="myCanvas"
                :width="hbwidth"
                :height="hbheight"
                :style="{
                  cursor: myStyle,
                  backgroundColor: atlasTypeName == '插画' ? '#ffff' : 'black',
                }"
              >
              </canvas>

              <!--           @mousedown="currentMode == 'drawing' ? startDrawing : null"
            @mouseup="currentMode == 'drawing' ? stopDrawing : null"
            @mousemove="currentMode == 'drawing' ? draws : null" -->
              <canvas
                v-show="isCanvasVisible"
                id="overlayCanvas"
                :width="hbwidth"
                :height="hbheight"
                ref="overlayCanvas"
                @touchstart="startDrawing"
                @touchend="stopDrawing"
                @touchmove="draws"
                @mousedown="startDrawing"
                @mouseup="stopDrawing"
                @mousemove="draws"
                @click="showTextInput"
                :style="{ cursor: currentCursorStyle }"
              >
              </canvas>
              <!-- <div class="overlayCanvastool" v-show="isCanvasVisible">
              <div
                  class="overlayCanvastooitem"
                  :class="
                    currentMode == 'text' ? 'overlayCanvastooitems' : null
                  "
                  @click="enableTextMode"
                  >T</div
                > 

               <div class="overlayCanvastooitem" @click="clearOverlay"
                  >删除</div
                >
                <div>
                  <input
                    id="size"
                    type="range"
                    min="1"
                    max="10"
                    v-model="brushSize"
                  />
                </div>
              </div> -->
              <div
                v-if="showInput"
                :style="inputStyle"
                class="text-input-container"
              >
                <input
                  v-model="customText"
                  @keydown.enter="addTextMarkerOnEnter"
                  class="text-input"
                  placeholder="输入要添加的文字"
                  @focus="isInputActive = true"
                  @blur="handleInputBlur"
                />
              </div>
            </div>
            <!-- 底部图片轮播 -->
            <div class="lboxmain">
              <!-- 页码 -->
              <div class="gnbottom" v-if="!loding">
                <div class="mentox">影像页数: </div>
                <div class="mentoxs">
                  <div class="tool" @click="tagdcoms('-1')">
                    <img src="@/images/letac.png" alt="" class="normal" />
                    <img src="@/images/let.png" alt="" class="active" />
                  </div>
                  <span>{{ findindex() + 1 }}/{{ imgsrc.length }}</span>
                  <div class="tool" @click="tagdcoms('1')">
                    <img src="@/images/rght.png" alt="" class="normal" />
                    <img src="@/images/rghtac.png" alt="" class="active" />
                  </div>
                </div>
              </div>
              <!-- 影像图 -->
              <div class="lbox" ref="gosroll" @scroll="getScrollPosition">
                <div
                  v-for="(item, index) in imgsrc"
                  :key="index"
                  class="lboxitem"
                  @click="tagdcom(item.medicineAtlasImgId, '')"
                >
                  <img :src="`${base + item.imgUrl}`" />
                  <div
                    class="msx"
                    v-if="item.medicineAtlasImgId == dcomid"
                  ></div>
                </div>
              </div>
            </div>
          </div>

          <!-- 分右侧区域 -->
          <!-- 菜单 -->
          <div class="bocd beautifulScroll">
            <div class="mentname">
              <div class="menttitle">
                <img src="@/images/cdicon.png" alt="" />
                菜单
              </div>
            </div>
            <div class="mentbjbox">
              <div class="mentbjtitle"> 标记 </div>
              <div class="mentbjtiem">
                <div class="jgdovx mentbjtiems">
                  添加批注
                  <el-switch v-model="pzshow" @change="pzfn()" />
                </div>
              </div>
              <div class="mentbjtiem">
                <div class="jgdovx mentbjtiems">
                  局部标签
                  <el-switch v-model="jubushow" @change="jubu()" />
                </div>
              </div>
              <div class="mentbjacitem" v-show="isCanvasVisible">
                <div class="tool mentbjacitemtool" @click="undo">
                  <img src="@/images/m1.png" alt="" class="normal" />
                  <img src="@/images/m1ac.png" alt="" class="active" />
                </div>
                <div class="tool mentbjacitemtool" @click="redo">
                  <img src="@/images/m2.png" alt="" class="normal" />
                  <img src="@/images/m2ac.png" alt="" class="active" />
                </div>
                <div class="tool mentbjacitemtool" @click="enableDrawingMode">
                  <img src="@/images/m3.png" alt="" class="normal" />
                  <img src="@/images/m3ac.png" alt="" class="active" />
                </div>
                <div class="tool mentbjacitemtool" @click="toggleEraser">
                  <img src="@/images/m4.png" alt="" class="normal" />
                  <img src="@/images/m4ac.png" alt="" class="active" />
                </div>
                <div class="tool mentbjacitemtool" style="position: relative">
                  <input
                    id="color"
                    type="color"
                    v-model="brushColor"
                    class="colorts"
                  />
                  <img src="@/images/m5.png" alt="" class="normal" />
                  <img src="@/images/m5ac.png" alt="" class="active" />
                </div>
                <div
                  class="tool mentbjacitemtool"
                  style="position: relative"
                  @click="hbcshow = !hbcshow"
                >
                  <div class="hbcbox" v-if="hbcshow">
                    <div
                      class="hbcitem"
                      @click="(brushSize = item), (hbcshow = false)"
                      v-for="item in brushSizedata"
                      :style="{
                        border: item + 'px solid #ffffff',
                      }"
                    ></div>
                  </div>
                  <img src="@/images/m6.png" alt="" class="normal" />
                  <img src="@/images/m6ac.png" alt="" class="active" />
                </div>
                <div class="tool mentbjacitemtool" @click="downloadImage">
                  <img src="@/images/m7.png" alt="" class="normal" />
                  <img src="@/images/m7ac.png" alt="" class="active" />
                </div>
              </div>
            </div>

            <div class="mentbjbox">
              <div class="mentbjtitle">筛选</div>
              <div class="mentsxbox">
                <div class="mentsxtitle">扫描方向</div>
                <div class="mentsxtitembox">
                  <div
                    :class="
                      classificationName == '全部'
                        ? 'mentsxitems'
                        : 'mentsxitem'
                    "
                    @click="changeimgclassfn('全部')"
                    >全部</div
                  >
                  <div
                    :class="
                      classificationName == item.classificationName
                        ? 'mentsxitems'
                        : 'mentsxitem'
                    "
                    v-for="item in imgclassdata"
                    @click="changeimgclassfn(item.classificationName)"
                    >{{ item.classificationName }}</div
                  >
                </div>
              </div>
              <div class="mentsxbox" v-show="imggroup.length > 0">
                <div class="mentsxtitle">加权</div>
                <div class="mentsxtitembox">
                  <div
                    :class="
                      imggroupname == '全部' ? 'mentsxitems' : 'mentsxitem'
                    "
                    @click="changeimggroupfn('全部', true)"
                    >全部</div
                  >
                  <div
                    v-for="(item, index) in imggroup"
                    :key="index"
                    :class="
                      imggroupname == item.typeName ? 'mentsxitems' : 'mentsxitem'
                    "
                    @click="changeimggroupfn(item.typeName, true)"
                    >{{ item.typeName }}</div
                  >
                </div>
              </div>
            </div>

   
            <div class="mentbjbox">
              <div class="mentbjtitle">解剖部位</div>

              <div class="mentbjtiem" v-if="optionsdata.length > 0">
                <div class="jgdovx mentbjtiems">
                  全部
                  <el-switch v-model="allflag" @change="changecsd()" />
                </div>
              </div>
              <div
                class="mentbjtiem"
                v-for="(item, index) in anatomicStructure"
                :key="index"
                v-show="flagfn(item)"
              >
                <div class="jgdovx mentbjtiems">
                  {{ item.anatomicStructureName }}
                  <el-switch v-model="item.flag" @change="changecs(item)" />
                </div>
              </div>
            </div>



          </div>
        </div>
      </div>
    </div>

    <!-- 知识点补充div -->
    <div class="zsbox" v-if="visible">
      <div class="mentname">
        <div class="menttitle">
          <img src="@/images/cdicon.png" alt="" />
          知识点补充
        </div>
        <div class="mentright" @click="visible = false">
          <img src="@/images/close-circle-filled.png" alt="" class="clseo" />
        </div>
      </div>

      <div class="zsbot">
        <div class="zsdkz">
          {{ bwstuddata.system }}> {{ bwstuddata.partsName }}>
          {{ bwstuddata.anatomicStructureName }}> {{ bwstuddata.pointName }}({{
            bwstuddata.pointNameEng
          }})

          <div v-if="bwstuddata.pointContent != ''">
            <v-md-preview
              :text="bwstuddata.pointContent"
              class="zsdkz"
            ></v-md-preview>
            <!-- <div class="zsdkz" v-html="bwstuddata.pointContent"> </div
          >-->
          </div>
          <div v-else>
            <div class="zsdkz">暂无知识点补充!</div>
          </div>
        </div></div
      >
    </div>

    <!-- 加载页 -->
    <div class="loader-container" v-if="loding">
      <div class="loader"></div>
      <p class="pd">加载中98%</p>
    </div>

    
  </div>
</template>

<script>

import {
  getPoint,
  getPointnew,
  getxqPoint,
  getPointjs,
  jpList,
  tpxqList,
} from '@/api/atlas';
import { debounce } from 'lodash';
import { useUserStore } from '@/store';
import router from '@/router';

export default {
  name: 'Atlas',
 
  data() {
    return {
      loding: false,
      lodings: false,
      medicineAtlasId: this.$route.query.medicineAtlasId,
      atlasTypeName: this.$route.query.atlasTypeName,
      imggroup: [],
      imgsrc: [],
      imgsrcs: [],
      imgclassdata: [],
      box: null,
      markingPointsIdxz: '',
      optionsselect: [],
      visible: false,
      base: window.config.VUE_FILE_BASE_PATH,
      canvasHistory: [], // 添加画布历史记录数组
      redoHistory: [], // 添加重做历史记录数组
      state: {
        labels: null,
        showText: true,
        canBiaoZhu: false,
        pointColor: '#65FF00',
        pointSize: 7,
        imgScale: 1,
        zoomStep: 0.1,
        markers: [],
        canvas: null,
        ctx: null,
        img: new Image(),
        imgWidth: 480,
        imgHeight: 606,
        imgPosition: { x: 0, y: 0 },
        currentText: '',
        currentMarker: {},
        showLinesAndText: true,
        isDragging: false,
        startDragX: 0,
        startDragY: 0,
        imgOffsetX: 0,
        imgOffsetY: 0,
        isSpacePressed: false,
        hoveredMarker: null,
        editingMarker: false,
        editPanelX: 0,
        editPanelY: 0,
        addflag: false,
        flipHorizontal: false,
        flipVertical: false,
        rotation: 0
      },
      markingPointsId: '',
      dcomid: Number(localStorage.getItem('dcomid')) || 1,
      startshow: false,
      addbsshowlx: false,
      visiblest: false,
      formModel: {
        userText: ''
      },
      bwstuddata: null,
      optionsdata: [
        { anatomicStructureName: '', flag: true, anatomicStructureId: '' }
      ],
      gosroll: null,
      jiegoudata: [],
      oneshow: false,
      startX: 0,
      startY: 0,
      isSwiping: false,
      startTime: 0,
      threshold: 30,
      fastSwipeThreshold: 200,
      fastSwipeDistance: 50,
      slowSwipeThreshold: 10,
      slowSwipeTimeThreshold: 200,
      isFastSwipe: false,
      hasMoved: false,
      tdflag: false,
      flag: false,
      hbheight: null,
      hbwidth: null,
      leftMarkers: [],
      rightMarkers: [],
      textModeEnabled: false,
      jubushow: false,
      pzshow: false,
      myStyle: 'inherit',
      context: null,
      overlayContext: null,
      isDrawing: false,
      isCanvasVisible: false,
      customText: '',
      showInput: false,
      inputStyle: {
        left: '',
        top: '',
        position: 'absolute'
      },
      isInputActive: false,
      currentMode: null,
      currentCursorStyle: 'inherit',
      brushColor: '#ff0000',
      brushSize: 2,
      isEraserMode: false,
      hbcshow: false,
      brushSizedata: [1, 2, 2.5, 3, 3.5, 4],
      allflag: true,
      classificationName: '全部',
      imggroupname: '全部',
      anatomicStructure: [
        {
          anatomicStructureName: '',
          flag: false,
          anatomicStructureId: ''
        }
      ]
    }
  },
  computed: {
    userdata() {
      return this.$store.state.user
    }
  },
  created() {
   
    this.gettpxq()
  },
  mounted() {
    this.handleResize = debounce(this.handleResize, 200)
    window.addEventListener('resize', this.handleResize)
    
    // 添加键盘事件监听
    document.addEventListener('keydown', this.handleKeyDown)
    document.addEventListener('keyup', this.handleKeyUp)
  },
  beforeDestroy() {
    const canvas = document.getElementById('myCanvas')
    if (canvas) {
      canvas.removeEventListener('wheel', this.handleWheel)
    }
    window.removeEventListener('resize', this.handleResize)
    document.removeEventListener('keydown', this.handleKeyDown)
    document.removeEventListener('keyup', this.handleKeyUp)
  },
  methods: {
    gettpxq() {
      this.loding = true
      tpxqList({ medicineAtlasId: this.medicineAtlasId }).then((res) => {
        if (res.code == 200) {
          this.imgsrc = res.data.allImg
          this.imgsrcs = res.data.allImg
          this.imggroup = res.data.group
          this.imgclassdata = res.data.classification
          this.lodings = true
          
          // 确保 box 元素已经挂载
          this.$nextTick(() => {
            if (!this.$refs.box) {
              console.warn('Box element not found')
              this.loding = false
              return
            }
            
            this.hbheight = this.$refs.box.offsetHeight
            this.hbwidth = this.$refs.box.offsetWidth
            
            // 初始化画布
            this.state.canvas = document.getElementById('myCanvas')
            if (!this.state.canvas) {
              console.warn('Canvas element not found')
              this.loding = false
              return
            }
            
            this.state.ctx = this.state.canvas.getContext('2d', {
              willReadFrequently: true
            })
            this.state.img = new Image()
            this.state.img.crossOrigin = 'anonymous'
            
            const imgsrcd = this.imgsrc.find(
              (item) => item.medicineAtlasImgId == this.dcomid
            )
            
            if (!imgsrcd) {
              this.state.img.src = this.base + this.imgsrc[0].imgUrl
              this.dcomid = this.imgsrc[0].medicineAtlasImgId
            } else {
              this.state.img.src = this.base + imgsrcd.imgUrl
            }
            
            this.state.img.onload = () => {
              this.state.imgWidth = this.state.img.naturalWidth
              this.state.imgHeight = this.state.img.naturalHeight
              this.loadMarkers()
              
              // 在数据加载完成后添加事件监听
              if (this.state.canvas) {
                this.state.canvas.addEventListener('wheel', this.handleWheel, { passive: false })
                this.state.canvas.addEventListener('mousedown', this.startDrag)
                this.state.canvas.addEventListener('mousemove', this.handleMouseMove)
                this.state.canvas.addEventListener('mouseup', this.stopDrag)
                this.state.canvas.addEventListener('mouseleave', this.stopDrag)
                this.state.canvas.addEventListener('click', this.handleCanvasClick)
                this.state.canvas.addEventListener('touchstart', this.handleTouchStart, { passive: false })
                this.state.canvas.addEventListener('touchmove', this.handleTouchMove, { passive: false })
                this.state.canvas.addEventListener('touchend', this.handleTouchEnd, { passive: false })
              }
              
              getPointnew({
                medicineAtlasId: this.medicineAtlasId,
                pageNum: 1,
                pageSize: 800
              }).then((res) => {
                if (res.code == 200) {
                  this.state.markers = []
                  this.saveMarkers()
                  const markersMap = new Map(
                    this.state.markers.map((marker) => [
                      marker.medicineAtlasImgId,
                      marker
                    ])
                  )
                  for (const items of res.data) {
                    try {
                      if (items.medicineAtlasImgId != null) {
                        const existingMarker = markersMap.get(items.medicineAtlasImgId)
                        const markingPointsObjects = JSON.parse(items.markingPoints)
                        markingPointsObjects.medicineAtlasImgId = items.medicineAtlasImgId
                        markingPointsObjects.bsdata[0].markingPointsId = items.markingPointsId
                        markingPointsObjects.bsdata[0].flag = true
                        markingPointsObjects.bsdata[0].labels = true
                        markingPointsObjects.bsdata[0].anatomicStructureName = items.anatomicStructureName
                        markingPointsObjects.bsdata[0].anatomicStructureId = items.anatomicStructureId
                        if (existingMarker) {
                          existingMarker.bsdata.push(...markingPointsObjects.bsdata)
                        } else {
                          markersMap.set(items.medicineAtlasImgId, markingPointsObjects)
                        }
                      }
                    } catch (error) {
                      console.error('Error processing item:', items, error)
                    }
                  }
                  this.state.markers = Array.from(markersMap.values())
                  
                  // 获取解剖结构数据
                  jpList({
                    medicineAtlasId: this.medicineAtlasId,
                    pageNum: 1,
                    pageSize: 999
                  }).then((res) => {
                    if (res.code == 200) {
                      this.optionsdata = res.data.list.map((item) => {
                        return { ...item, flag: true }
                      })
                      
                      this.anatomicStructurefn()
                    }
                  })
                  
                  this.draw('')
                  this.loding = false
                }
              })
            }
            
            this.state.img.onerror = (error) => {
              console.error('Failed to load image:', error)
              this.loding = false
            }
          })
        }
      })
    },
    handleResize() {
      if (this.$refs.box) {
        this.hbheight = this.$refs.box.offsetHeight
        this.hbwidth = this.$refs.box.offsetWidth
        
        // 重新设置画布尺寸
        const canvas = document.getElementById('myCanvas')
        if (canvas) {
          canvas.width = this.hbwidth
          canvas.height = this.hbheight
        }
        
        // 重新设置覆盖层画布尺寸
        const overlayCanvas = document.getElementById('overlayCanvas')
        if (overlayCanvas) {
          overlayCanvas.width = this.hbwidth
          overlayCanvas.height = this.hbheight
        }
        
        // 重新加载图片并绘制
        const imgsrcd = this.imgsrc.find(item => item.medicineAtlasImgId === this.dcomid)
        if (imgsrcd) {
          this.state.img.src = this.base + imgsrcd.imgUrl
          this.state.img.onload = () => {
            this.state.imgWidth = this.state.img.naturalWidth
            this.state.imgHeight = this.state.img.naturalHeight
            this.draw('')
          }
        }
      }
    },
    handleKeyDown(event) {
      if (event.key === ' ') {
        this.state.isSpacePressed = true
      }
    },
    handleKeyUp(event) {
      if (event.key === ' ') {
        this.state.isSpacePressed = false
      }
    },
    handleTouchStart(event) {
      event.preventDefault()
      if (event.touches.length === 2) {
        this.startX = event.touches[0].clientX
        this.startY = event.touches[0].clientY
        this.isSwiping = true
        this.startTime = Date.now()
      }
    },
    handleTouchMove(event) {
      if (!this.isSwiping) return
      event.preventDefault()
      const currentX = event.touches[0].clientX
      const currentY = event.touches[0].clientY
      const deltaX = currentX - this.startX
      const deltaY = currentY - this.startY
      const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY)
      const timeElapsed = Date.now() - this.startTime
      if (distance > this.threshold) {
        this.hasMoved = true
        if (distance > this.fastSwipeDistance && timeElapsed < this.fastSwipeThreshold) {
          this.isFastSwipe = true
        }
      }
    },
    handleTouchEnd(event) {
      if (!this.isSwiping) return
      event.preventDefault()
      this.isSwiping = false
      if (this.hasMoved) {
        if (this.isFastSwipe) {
          this.handleFastSwipe()
        } else {
          this.handleSlowSwipe()
        }
      }
      this.hasMoved = false
      this.isFastSwipe = false
    },
    handleFastSwipe() {
      const currentIndex = this.findindex()
      if (this.startX > this.$refs.box.offsetWidth / 2) {
        this.tagdcoms('1')
      } else {
        this.tagdcoms('-1')
      }
    },
    handleSlowSwipe() {
      const currentIndex = this.findindex()
      if (this.startX > this.$refs.box.offsetWidth / 2) {
        this.tagdcoms('1')
      } else {
        this.tagdcoms('-1')
      }
    },
    touchStartHandler(event) {
      if (event.touches.length === 2) {
        this.startX = event.touches[0].clientX
        this.startY = event.touches[0].clientY
        this.isSwiping = true
        this.startTime = Date.now()
      }
    },
    touchMoveHandler(event) {
      if (!this.isSwiping) return
      const currentX = event.touches[0].clientX
      const currentY = event.touches[0].clientY
      const deltaX = currentX - this.startX
      const deltaY = currentY - this.startY
      const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY)
      const timeElapsed = Date.now() - this.startTime
      if (distance > this.threshold) {
        this.hasMoved = true
        if (distance > this.fastSwipeDistance && timeElapsed < this.fastSwipeThreshold) {
          this.isFastSwipe = true
        }
      }
    },
    touchEndHandler(event) {
      if (!this.isSwiping) return
      this.isSwiping = false
      if (this.hasMoved) {
        if (this.isFastSwipe) {
          this.handleFastSwipe()
        } else {
          this.handleSlowSwipe()
        }
      }
      this.hasMoved = false
      this.isFastSwipe = false
    },
    startDrag(e) {
      if (!this.tdflag) {
        return
      }
      console.log('当前拖动标记')
      // 判断是否为触摸事件
      const isTouchEvent = 'touches' in e

      let clientX, clientY

      if (isTouchEvent) {
        // 触摸事件
        clientX = e.touches[0].clientX
        clientY = e.touches[0].clientY
        e.preventDefault() // 仅在触摸事件时调用 preventDefault
      } else {
        // 鼠标事件
        clientX = e.clientX
        clientY = e.clientY
        if (e.button === 0) {
          e.preventDefault() // 仅在左键点击时调用 preventDefault
        }
      }

      // 判断是否为左键点击或触摸
      if ((e instanceof MouseEvent && e.button === 0) || isTouchEvent) {
        if (this.tdflag) {
          this.state.isDragging = true

          // 获取 canvas 的位置和尺寸
          const rect = this.state.canvas.getBoundingClientRect()
          console.log('Canvas rect:', rect) // 输出 rect 检查是否精确

          // 确保在计算开始位置时能处理动态变化
          this.state.startDragX = clientX - rect.left - this.state.imgOffsetX
          this.state.startDragY = clientY - rect.top - this.state.imgOffsetY
        }
      }
    },
    handleMouseMove(event) {
      // 判断是否为触摸事件
      const isTouchEvent = 'touches' in event
      let canvasX, canvasY

      if (isTouchEvent) {
        // 获取触摸事件的坐标
        const touch = event.touches[0]
        const rect = this.state.canvas.getBoundingClientRect()
        canvasX = touch.clientX - rect.left
        canvasY = touch.clientY - rect.top
      } else {
        // 获取鼠标事件的坐标
        canvasX = event.offsetX
        canvasY = event.offsetY
      }

      if (this.state.isDragging) {
        this.dragMove(event)
      } else {
        this.checkHover(canvasX, canvasY)
        if (this.state.hoveredMarker) {
          this.draw('搜索')
        } else {
          this.draw('')
        }
      }
    },
    stopDrag() {
      this.state.isDragging = false
      this.tdflag = false
    },
    handleWheel(event) {
      event.preventDefault()
      const delta = event.deltaY > 0 ? 1 : -1
      this.tagdcoms(delta.toString())
    },
    handleCanvasClick(event) {
      let canvasX, canvasY

      if ('touches' in event) {
        // 触摸事件
        const touch = event.touches[0]
        const rect = this.state.canvas.getBoundingClientRect()
        canvasX = touch.clientX - rect.left
        canvasY = touch.clientY - rect.top
        this.checkHover(canvasX, canvasY)
        event.preventDefault()
      } else {
        // 鼠标事件
        canvasX = event.offsetX
        canvasY = event.offsetY
      }

      if (this.state.canBiaoZhu) {
        // 计算图像坐标
        const imgX = (canvasX - (this.state.canvas.width / 2 - (this.state.imgWidth * this.state.imgScale) / 2)) / this.state.imgScale
        const imgY = (canvasY - (this.state.canvas.height / 2 - (this.state.imgHeight * this.state.imgScale) / 2)) / this.state.imgScale
        this.createMarker(imgX, imgY)
      } else if (this.state.hoveredMarker) {
        this.state.currentMarker = this.state.hoveredMarker
        this.state.currentText = this.state.hoveredMarker.text || ''
        this.markingPointsId = this.state.hoveredMarker.markingPointsId

        this.draw(this.state.hoveredMarker)

        getxqPoint({ markPointsId: this.markingPointsId }).then((res) => {
          if (res.code === 200) {
            this.visible = false
            this.bwstuddata = res.data
            // 再次查询点位知识点 中英文对照
            getPointjs({ pointName: res.data.pointName }).then((resd) => {
              this.bwstuddata.pointNameEng = resd.data.pointNameEng || ''
              this.bwstuddata.pointContent = resd.data.pointContent
              this.handleClick()
            })
          }
        })
      }
    },
    checkHover(x, y) {
      this.state.hoveredMarker = null
      this.myStyle = 'inherit'
      
      // 从状态中解构出相关的属性
      const { markers, pointSize, imgScale } = this.state
      
      // 合并 bsdata
      const mergedBsdata = markers.filter(item => 
        item.medicineAtlasImgId.includes(this.dcomid)
      )
      const targetElement = { bsdata: [] }
      targetElement.bsdata = mergedBsdata.flatMap(item => item.bsdata)

      if (targetElement) {
        // 找到目标标记元素中的标记
        for (let marker of targetElement.bsdata) {
          // 获取画布和上下文
          const canvas = this.state.canvas
          const ctx = this.state.ctx

          // 计算缩放后的图像尺寸
          const scaledWidth = this.state.imgWidth * imgScale
          const scaledHeight = this.state.imgHeight * imgScale

          // 计算图像在画布上的偏移量
          const xOffset = (canvas.width - scaledWidth) / 2 + this.state.imgOffsetX
          const yOffset = (canvas.height - scaledHeight) / 2 + this.state.imgOffsetY

          // 计算标记的位置
          const markerX = marker.x * imgScale + xOffset
          const markerY = marker.y * imgScale + yOffset

          // 检查是否悬停在标记点上
          if (Math.hypot(x - markerX, y - markerY) < (pointSize / 2) * imgScale * 3) {
            this.state.hoveredMarker = marker
            this.myStyle = 'pointer'
            return true
          }

          // 检查是否悬停在文本上
          const text = marker.text || ''
          ctx.font = '12px Arial' // 根据实际使用的字体进行设置
          const textMetrics = ctx.measureText(text)
          const textWidth = textMetrics.width

          const textX = marker.textX
          const textY = marker.textY
          const textHeight = 14 * imgScale

          // 计算文本的边界框
          const textBoundingBox = {
            left: textX - textWidth - 100,
            right: textX + textWidth + 100,
            top: textY - textHeight,
            bottom: textY
          }

          if (
            x >= textBoundingBox.left &&
            x <= textBoundingBox.right &&
            y >= textBoundingBox.top &&
            y <= textBoundingBox.bottom
          ) {
            this.myStyle = 'pointer'
            this.state.hoveredMarker = marker
            return true
          }
        }
      }

      // 没有悬停在任何标记、线段或文本上
      this.state.hoveredMarker = null
      return false
    },
    dragMove(e) {
      // 判断是否是鼠标事件还是触摸事件
      const clientX = e instanceof MouseEvent ? e.clientX : e.touches[0].clientX
      const clientY = e instanceof MouseEvent ? e.clientY : e.touches[0].clientY

      if (this.state.isDragging) {
        const rect = this.state.canvas.getBoundingClientRect()
        this.state.imgOffsetX = clientX - rect.left - this.state.startDragX
        this.state.imgOffsetY = clientY - rect.top - this.state.startDragY
        this.draw('')
      }
    },
    createMarker(x, y) {
      // 创建新标记的逻辑
      const newMarker = {
        x,
        y,
        text: '',
        color: this.state.pointColor,
        flag: true,
        labels: true
      }

      // 添加到当前图片的标记中
      const currentImageMarkers = this.state.markers.find(
        marker => marker.medicineAtlasImgId === this.dcomid
      )

      if (currentImageMarkers) {
        currentImageMarkers.bsdata.push(newMarker)
      } else {
        this.state.markers.push({
          medicineAtlasImgId: this.dcomid,
          bsdata: [newMarker]
        })
      }

      this.saveMarkers()
      this.draw('')
    },
    handleClick() {
      this.visible = true
    },
    loadMarkers() {
      const savedMarkers = localStorage.getItem('markers')
      if (savedMarkers) {
        this.state.markers = JSON.parse(savedMarkers)
      }
    },
    saveMarkers() {
      localStorage.setItem('markers', JSON.stringify(this.state.markers))
    },
    draw(type) {
    
      if (!this.state.ctx || !this.state.img || !this.state.canvas) {
        console.warn('Canvas or image not ready')
        return
      }
      if (this.state.imgWidth == 0) {
        console.warn('Image width is 0')
        return
      }

      const canvas = this.state.canvas
      const ctx = this.state.ctx
      const img = this.state.img

      // 清空画布
      ctx.clearRect(0, 0, canvas.width, canvas.height)

      const scaledWidth = this.state.img.naturalWidth * this.state.imgScale
      const scaledHeight = this.state.img.naturalHeight * this.state.imgScale

      // 计算图像在画布上的偏移
      const xOffset = (canvas.width - scaledWidth) / 2 + this.state.imgOffsetX
      const yOffset = (canvas.height - scaledHeight) / 2 + this.state.imgOffsetY

      ctx.save()

      // 应用变换
      ctx.translate(canvas.width / 2, canvas.height / 2)
      if (this.state.flipHorizontal) ctx.scale(-1, 1)
      if (this.state.flipVertical) ctx.scale(1, -1)
      ctx.rotate((this.state.rotation * Math.PI) / 180)
      ctx.translate(-canvas.width / 2, -canvas.height / 2)

      // 绘制图像
      ctx.drawImage(img, xOffset, yOffset, scaledWidth, scaledHeight)

      // 恢复上下文状态为绘制标记做准备
      ctx.restore()
      ctx.save()

      // 重新应用变换
      ctx.translate(canvas.width / 2, canvas.height / 2)
      if (this.state.flipHorizontal) ctx.scale(-1, 1)
      if (this.state.flipVertical) ctx.scale(1, -1)
      ctx.rotate((this.state.rotation * Math.PI) / 180)
      ctx.translate(-canvas.width / 2, -canvas.height / 2)

      const margin = 200 // 从画布边缘的边距
      let textHeight = 16 // 文本高度
      let verticalSpacing = 5 // 文本之间的垂直间隔
      const textMargin = 20 // 文本与边缘的距离

      // 记录所有标记的位置和文本
      this.leftMarkers = []
      this.rightMarkers = []

      // 定义绘制标记和文本的函数
      const drawMarkersAndText = (markers, isLeft) => {
        markers.forEach((item) => {
          if (!item.medicineAtlasImgId) return
          const itemsArray = item.medicineAtlasImgId.split(',').map(Number)

          if (itemsArray.includes(this.dcomid)) {
            item.bsdata.forEach((marker) => {
              const markerX = marker.x * this.state.imgScale + xOffset
              const markerY = marker.y * this.state.imgScale + yOffset

              // 划分左右位置数组保存
              const count = this.leftMarkers.filter(item => item.flag == true).length
              const counts = this.rightMarkers.filter(item => item.flag == true).length

              // 根据位置将标记存入对应数组
              if (isLeft) {
                if (markerX < canvas.width / 2) {
                  if (count > 23) {
                    this.leftMarkers.push(marker)
                  } else {
                    marker.lintextshow = marker.flag
                    this.leftMarkers.push(marker)
                  }
                }
              } else {
                if (markerX >= canvas.width / 2) {
                  if (counts > 23) {
                    marker.lintextshow = false
                    this.rightMarkers.push(marker)
                  } else {
                    marker.lintextshow = marker.flag
                    this.rightMarkers.push(marker)
                  }
                }
              }

              // 绘制标记点
              if (marker.flag) {
                if (marker.tack) {
                  // 开启大头针
                  ctx.beginPath()

                  // 定义大头针参数
                  const baseSize = this.state.pointSize
                  const radius = baseSize * 1.5
                  const height = baseSize * 3

                  // 绘制顶部圆形
                  ctx.arc(markerX, markerY, radius, Math.PI, 0, false)

                  // 绘制底部尖角
                  ctx.lineTo(markerX, markerY + height)
                  ctx.lineTo(markerX - radius, markerY)

                  // 完成路径
                  ctx.closePath()

                  // 设置样式并填充
                  ctx.fillStyle = marker == this.state.hoveredMarker ? '#409EFF' : '#' + marker.color
                  ctx.fill()

                  // 如果需要边框
                  ctx.lineWidth = 2
                  ctx.strokeStyle = 'black'
                  ctx.stroke()
                } else {
                  // 未开启大头针
                  ctx.fillStyle = marker == this.state.hoveredMarker ? '#409EFF' : '#' + marker.color

                  if (type == '搜索') {
                    ctx.fillStyle = marker == this.state.hoveredMarker ? 'rgba(255, 0, 0, 1)' : 'rgba(128, 128, 128, 0.5)'
                  }
                  ctx.beginPath()
                  ctx.arc(markerX, markerY, this.state.pointSize / 2, 0, 2 * Math.PI)
                  ctx.fill()
                }
              }
            })
          }
        })
      }

      // 绘制左侧和右侧的标记
      drawMarkersAndText(this.state.markers, true)
      drawMarkersAndText(this.state.markers, false)

      // 左右数组优化调整顺序
      this.leftMarkers.sort((a, b) => a.y - b.y)
      this.rightMarkers.sort((a, b) => a.y - b.y)

      // 可用区域的总高度
      const availableHeight = canvas.height - 2 * textMargin - 30

      // 处理左侧或右侧数据
      const calculateStartYAndHeight = (markers) => {
        const markerCount = markers.length

        if (markerCount === 0) {
          return { totalTextHeight: 0, startY: textMargin }
        }

        // 计算总文本高度
        let totalTextHeight = markerCount * (textHeight + verticalSpacing) - verticalSpacing

        // 动态调整文本大小和间距
        if (totalTextHeight < availableHeight / 2) {
          const scaleFactor = availableHeight / (2 * totalTextHeight)
          textHeight *= Math.min(scaleFactor, 1.3)
          verticalSpacing *= Math.min(scaleFactor, 1.5)
          totalTextHeight = markerCount * (textHeight + verticalSpacing) - verticalSpacing
        }

        // 计算起始位置
        const startY = Math.max(textMargin, (availableHeight - totalTextHeight) / 2 + textMargin)

        return { totalTextHeight, startY }
      }

      // 计算每个文本的位置
      const calculateTextPositions = (markers, startY) => {
        let yPosition = startY
        let lastYPosition = startY
        let lastLineCount = 1
        let lastText = ''

        markers.forEach((marker) => {
          if (marker.flag) {
            const maxTextWidth = margin
            ctx.font = `${textHeight}px Arial`
            let lines = []
            let currentLine = ''
            for (let i = 0; i < lastText.length; i++) {
              const char = lastText[i]
              const testLine = currentLine + char
              const testWidth = ctx.measureText(testLine).width

              if (testWidth > maxTextWidth) {
                lines.push(currentLine)
                currentLine = char
              } else {
                currentLine = testLine
              }
            }

            if (currentLine) {
              lines.push(currentLine)
            }

            lastLineCount = lines.length

            if (yPosition + textHeight > availableHeight) {
              marker.lintextshow = marker === type
              if (marker.lintextshow) {
                markers[0].lintextshow = false
                marker.textY = markers[0].textY
              }
            } else {
              marker.lintextshow = true
              yPosition = lastYPosition + lastLineCount * textHeight + verticalSpacing * lastLineCount
              marker.textY = yPosition
            }

            lastYPosition = marker.textY
            lastText = marker.text
          }
        })
      }

      // 分别计算左侧和右侧文本位置
      const { startY: leftStartY } = calculateStartYAndHeight(this.leftMarkers)
      const { startY: rightStartY } = calculateStartYAndHeight(this.rightMarkers)

      calculateTextPositions(this.leftMarkers, leftStartY)
      calculateTextPositions(this.rightMarkers, rightStartY)

      // 定义绘制文本和线条的函数
      const drawTextAndLines = (markers, isLeft) => {
        markers.forEach((marker, index) => {
          const { text, textY } = marker
          const markerX = marker.x * this.state.imgScale + xOffset
          const markerY = marker.y * this.state.imgScale + yOffset
          const textX = isLeft ? margin : canvas.width - margin

          if (marker.lintextshow && marker.flag && marker.labels && !marker.tack) {
            ctx.strokeStyle = marker == this.state.hoveredMarker ? '#409EFF' : '#' + marker.color
            if (type == '搜索') {
              ctx.strokeStyle = marker == this.state.hoveredMarker ? 'rgba(255, 0, 0, 1)' : 'rgba(128, 128, 128, 0.5)'
            }

            ctx.lineWidth = 1.5
            ctx.beginPath()
            ctx.moveTo(markerX, markerY)

            // 确定线条结束点
            const lineEndX = isLeft ? Math.max(textX, margin + 20) : Math.min(textX, canvas.width - margin - 20)
            ctx.lineTo(lineEndX, textY)
            ctx.stroke()

            // 判断左右
            if (isLeft) {
              const horizontalLineLength = 10
              ctx.lineTo(lineEndX - horizontalLineLength, textY)
              const verticalLineHeight = 5
              ctx.lineTo(lineEndX - horizontalLineLength, textY - 10 - verticalLineHeight)
              ctx.stroke()
            } else {
              const horizontalLineLength = 10
              ctx.lineTo(lineEndX + horizontalLineLength, textY)
              const verticalLineHeight = 5
              ctx.lineTo(lineEndX + horizontalLineLength, textY - 10 - verticalLineHeight)
              ctx.stroke()
            }

            // 计算文本换行
            const maxTextWidth = margin
            let lineY = textY
            let lines = []
            let currentLine = ''
            for (let i = 0; i < text.length; i++) {
              const char = text[i]
              const testLine = currentLine + char
              const testWidth = ctx.measureText(testLine).width

              if (testWidth > maxTextWidth) {
                lines.push(currentLine)
                currentLine = char
              } else {
                currentLine = testLine
              }
            }

            if (currentLine) {
              lines.push(currentLine)
            }

            // 绘制每一行文本
            lines.forEach((line, lineIndex) => {
              ctx.fillStyle = marker == this.state.hoveredMarker ? '#409EFF' : '#' + marker.color
              if (type == '搜索') {
                ctx.fillStyle = marker == this.state.hoveredMarker ? 'rgba(255, 0, 0, 1)' : 'rgba(128, 128, 128, 0.5)'
              }

              ctx.textAlign = isLeft ? 'right' : 'left'
              ctx.font = `${textHeight}px Arial`

              const adjustedTextY = lineY + lineIndex * (textHeight + verticalSpacing)
              if (this.state.showText) {
                if (marker.userText) {
                  ctx.fillText(line + ' / ' + marker.userText || '', textX, adjustedTextY)
                } else {
                  ctx.fillText(line, textX, adjustedTextY)
                }
              } else {
                ctx.fillText(marker.userText || index + 1, textX, adjustedTextY)
              }
            })

            // 更新状态
            this.state.markers.forEach((item) => {
              if (!item.medicineAtlasImgId) return
              const itemsArray = item.medicineAtlasImgId.split(',').map(Number)
              if (itemsArray.includes(this.dcomid)) {
                item.bsdata.forEach((markers) => {
                  if (markers.markingPointsId == marker.markingPointsId) {
                    markers.textX = textX
                    markers.textY = lineY
                  }
                })
              }
            })
          }
        })
      }

      // 绘制左侧和右侧的文本和线条
      drawTextAndLines(this.leftMarkers, true)
      drawTextAndLines(this.rightMarkers, false)

      // 恢复上下文状态
      ctx.restore()
      this.loding = false
    },
    zoomIn() {
      this.state.imgScale = Math.min(3, this.state.imgScale + this.state.zoomStep)
      this.draw('')
    },
    zoomOut() {
      this.state.imgScale = Math.max(0.1, this.state.imgScale - this.state.zoomStep)
      this.draw('')
    },
    reset() {
      this.state.imgScale = 1
      this.state.imgOffsetX = 0
      this.state.imgOffsetY = 0
      this.state.rotation = 0
      this.state.flipHorizontal = false
      this.state.flipVertical = false
      this.draw('')
    },
    toggleLinesAndText() {
      this.state.showLinesAndText = !this.state.showLinesAndText
      this.draw('')
    },
    flipHorizontald() {
      this.state.flipHorizontal = !this.state.flipHorizontal
      this.draw('')
    },
    flipVerticald() {
      this.state.flipVertical = !this.state.flipVertical
      this.draw('')
    },
    rotate90() {
      this.state.rotation = (this.state.rotation + 90) % 360
      this.draw('')
    },
    rotateMinus90() {
      this.state.rotation = (this.state.rotation - 90) % 360
      this.draw('')
    },
    anatomicStructurefn() {
      this.anatomicStructure = []
      this.optionsdata.forEach((items) => {
        this.state.markers.some((item) => {
          if (!item.medicineAtlasImgId) {
            return
          }

          const itemsArray = item.medicineAtlasImgId.split(',').map(Number)
          if (itemsArray.includes(this.dcomid)) {
            item.bsdata.forEach((itemd) => {
              if (itemd.anatomicStructureId == items.anatomicStructureId) {
                // 先检查是否已存在
                const exists = this.anatomicStructure.some(
                  (a) => a.anatomicStructureId === items.anatomicStructureId
                )

                if (!exists) {
                  this.anatomicStructure.push(items)
                }
              }
            })
          }
          return false
        })
      })
      console.log('处理完成的数据',this.anatomicStructure)
    },
    flagfn(item) {
      return this.state.markers.some((marker) => {
        const itemsArray = marker.medicineAtlasImgId.split(',').map(Number)
        if (itemsArray.includes(this.dcomid)) {
          return marker.bsdata.some(
            (itemd) => itemd.anatomicStructureId === item.anatomicStructureId
          )
        }
        return false
      })
    },
    changecs(item) {
      console.log('关联解剖结构测试', this.anatomicStructure, item)
      this.state.markers.some((marker) => {
        marker.bsdata.some((itemd) => {
          if (itemd.anatomicStructureId == item.anatomicStructureId) {
            itemd.flag = item.flag
          }
        })
      })

      // 判断是否存在 flag 为 false 的项
      this.allflag = !this.anatomicStructure.some(
        (item) => item.flag === false
      )

      this.draw('')
    },
    changeimgclassfn(name) {
      this.classificationName = name
      this.imgsrc = []
      this.imgsrcs.forEach(item => {
        if (this.classificationName === item.imgClassificationName) {
          this.imgsrc.push(item)
        }
      })

      if (name === '全部') {
        this.imggroupname = '全部'
        this.imgsrc = this.imgsrcs
        this.dcomid = this.imgsrc[0].medicineAtlasImgId
        this.tagdcom(this.dcomid, '')
        return
      }

      if (this.imggroupname !== '全部') {
        this.changeimggroupfn(this.imggroupname, false)
      }

      this.dcomid = this.imgsrc[0].medicineAtlasImgId
      this.tagdcom(this.dcomid, '')
    },
    changeimggroupfn(name, flag) {
      if (name === '全部' && flag) {
        this.imggroupname = '全部'
        this.changeimgclassfn(this.classificationName)
        return
      }

      this.imggroupname = name
      const item = this.imggroup.find(img => img.typeName === this.imggroupname)

      const imgsrcsd = item
      const imgsrcmw = this.imgsrc
      this.imgsrc = []

      // 判断解剖面是默认或者全选状态的时候默认选择第一个选项
      if (this.classificationName === '全部') {
        this.classificationName = this.imgclassdata[0].classificationName
      }

      // 判断完成
      if (this.classificationName !== '') {
        imgsrcsd.typeImg.forEach(itemd => {
          if (
            this.classificationName === itemd.imgClassificationName &&
            this.imggroupname === itemd.typeName
          ) {
            this.imgsrc.push(itemd)
          }
        })
      } else {
        this.imgsrc = imgsrcsd.typeImg
      }

      if (this.imgsrc.length > 0) {
        this.dcomid = this.imgsrc[0].medicineAtlasImgId
        this.tagdcom(this.dcomid, '')
      } else {
        console.log('当前图像没有T2', this.imgsrc)
        this.imgsrc = imgsrcmw

        this.$message.warning('暂无图像，请更换其他解剖面后再选择加权！')
        this.imggroupname = '全部'
      }
    },
    findindex() {
      return this.imgsrc.findIndex(item => item.medicineAtlasImgId === this.dcomid)
    },
    tagdcom(id, type) {
      if (id) {
        this.dcomid = id
        localStorage.setItem('dcomid', id)
      }
      const imgsrcd = this.imgsrc.find(item => item.medicineAtlasImgId === this.dcomid)
      if (imgsrcd) {
        this.state.img.src = this.base + imgsrcd.imgUrl
        this.state.img.onload = () => {
          this.state.imgWidth = this.state.img.naturalWidth
          this.state.imgHeight = this.state.img.naturalHeight
          if(type=='搜索'){
            this.draw('搜索')
          }else{
            this.draw('')
          }
        }
      }
    },
    tagdcoms(type) {
      const currentIndex = this.findindex()
      let newIndex
      if (type === '1') {
        newIndex = (currentIndex + 1) % this.imgsrc.length
      } else {
        newIndex = (currentIndex - 1 + this.imgsrc.length) % this.imgsrc.length
      }
      this.tagdcom(this.imgsrc[newIndex].medicineAtlasImgId, '')
    },
    getScrollPosition(event) {
      const scrollLeft = event.target.scrollLeft
      const scrollWidth = event.target.scrollWidth
      const clientWidth = event.target.clientWidth
      if (scrollLeft + clientWidth >= scrollWidth) {
        this.tagdcoms('1')
      } else if (scrollLeft === 0) {
        this.tagdcoms('-1')
      }
    },
    goback() {
      this.$router.go(-1)
    },
    startfn() {
      this.startshow = true
    },
    startfns() {
      this.startshow = false
    },
    allclear() {
      this.state.markers = []
      this.saveMarkers()
      this.draw('')
    },
    toggleTextButton() {
      this.draw('')
    },
    pzfn() {
      this.isCanvasVisible = this.pzshow
      if (this.pzshow) {
        this.currentMode = 'drawing'
        this.currentCursorStyle = 'crosshair'
        
        this.$nextTick(() => {
          const myCanvas = document.getElementById('myCanvas')
          const overlayCanvas = document.getElementById('overlayCanvas')

          // 获取画布上下文
          this.context = myCanvas.getContext('2d', {
            willReadFrequently: true
          })
          this.overlayContext = overlayCanvas.getContext('2d', {
            willReadFrequently: true
          })

          // 保存初始状态
          this.canvasHistory.push(
            this.overlayContext.getImageData(0, 0, overlayCanvas.width, overlayCanvas.height)
          )
        })
      } else {
        this.currentMode = null
        this.currentCursorStyle = 'inherit'
        // 清除画布内容
        const overlayCanvas = this.$refs.overlayCanvas
        if (overlayCanvas) {
          const ctx = overlayCanvas.getContext('2d')
          ctx.clearRect(0, 0, overlayCanvas.width, overlayCanvas.height)
        }
      }
    },
    jubu() {
      const matchingItems = this.state.markers.filter(item => 
        item.medicineAtlasImgId.includes(this.dcomid)
      )

      matchingItems.forEach(item => {
        item.bsdata.forEach(items => {
          items.labels = !this.jubushow // 切换标签状态
        })
      })

      this.saveMarkers()
      this.draw('')

      const canvasContainer = document.getElementById('canvasContainer')
      if (!canvasContainer) return // 确保容器存在

      // 确保父容器是相对定位
      canvasContainer.style.position = 'relative'

      // 检查是否已有子画布，若存在则移除并退出
      const existingOverlayCanvas = canvasContainer.querySelector('canvas[data-role="overlay"]')
      if (existingOverlayCanvas) {
        canvasContainer.removeChild(existingOverlayCanvas)
        canvasContainer.querySelectorAll('div[data-role="resize-handle"]').forEach(circle => circle.remove())
        return // 不再执行后续代码
      }

      // 创建并设置新的子 canvas
      const overlayCanvas = document.createElement('canvas')
      overlayCanvas.width = 80
      overlayCanvas.height = 80
      overlayCanvas.style.cssText = `
        border: 1px solid ${this.atlasTypeName == '插画' ? 'red' : '#ffffff'};
        position: absolute;
        z-index: 10;
        left: 750px; /* 初始位置 */
        top: 350px; /* 初始位置 */
        cursor: move;
      `
      overlayCanvas.setAttribute('data-role', 'overlay') // 添加标识以便后续查找
      canvasContainer.appendChild(overlayCanvas)

      // 当前画布状态
      let currentState = {
        width: overlayCanvas.width,
        height: overlayCanvas.height,
        left: parseFloat(overlayCanvas.style.left),
        top: parseFloat(overlayCanvas.style.top)
      }

      // 是否在拖动模式
      let isDragging = false
      let dragOffsetX = 0
      let dragOffsetY = 0

      // 判断是否为触摸设备
      const isTouchDevice = 'ontouchstart' in window && window.matchMedia('(pointer: coarse)').matches

      // 画布拖动逻辑
      const startDragx = (e) => {
        e.preventDefault()
        isDragging = true
        const clientX = isTouchDevice ? e.touches[0].clientX : e.clientX
        const clientY = isTouchDevice ? e.touches[0].clientY : e.clientY
        dragOffsetX = clientX - overlayCanvas.offsetLeft
        dragOffsetY = clientY - overlayCanvas.offsetTop

        const onMove = (moveEvent) => {
          if (!isDragging) return
          const newX = (isTouchDevice ? moveEvent.touches[0].clientX : moveEvent.clientX) - dragOffsetX
          const newY = (isTouchDevice ? moveEvent.touches[0].clientY : moveEvent.clientY) - dragOffsetY
          currentState.left = newX
          currentState.top = newY

          overlayCanvas.style.left = `${newX}px`
          overlayCanvas.style.top = `${newY}px`

          updateControlPoints()
          updateMarkers() // 更新标记点状态
        }

        const stopDragx = () => {
          isDragging = false
          window.removeEventListener(isTouchDevice ? 'touchmove' : 'mousemove', onMove)
          window.removeEventListener(isTouchDevice ? 'touchend' : 'mouseup', stopDragx)
          this.draw('') // 拖动完成后更新画布
        }

        window.addEventListener(isTouchDevice ? 'touchmove' : 'mousemove', onMove)
        window.addEventListener(isTouchDevice ? 'touchend' : 'mouseup', stopDragx)
      }

      overlayCanvas.addEventListener(isTouchDevice ? 'touchstart' : 'mousedown', startDragx)

      // 更新圆点位置
      const updateControlPoints = () => {
        const canvasRect = overlayCanvas.getBoundingClientRect()
        const containerRect = canvasContainer.getBoundingClientRect()

        const controlPoints = [
          { x: canvasRect.left - containerRect.left, y: canvasRect.top - containerRect.top }, // 左上角
          { x: canvasRect.left - containerRect.left + canvasRect.width / 2, y: canvasRect.top - containerRect.top }, // 顶边中心
          { x: canvasRect.right - containerRect.left, y: canvasRect.top - containerRect.top }, // 右上角
          { x: canvasRect.left - containerRect.left, y: canvasRect.top - containerRect.top + canvasRect.height / 2 }, // 左边中心
          { x: canvasRect.right - containerRect.left, y: canvasRect.top - containerRect.top + canvasRect.height / 2 }, // 右边中心
          { x: canvasRect.left - containerRect.left, y: canvasRect.bottom - containerRect.top }, // 左下角
          { x: canvasRect.left - containerRect.left + canvasRect.width / 2, y: canvasRect.bottom - containerRect.top }, // 底边中心
          { x: canvasRect.right - containerRect.left, y: canvasRect.bottom - containerRect.top } // 右下角
        ]

        controlHandles.forEach((circle, index) => {
          circle.style.left = `${controlPoints[index].x - 5}px`
          circle.style.top = `${controlPoints[index].y - 5}px`
        })
      }

      // 更新标记点状态
      const updateMarkers = () => {
        const scaledWidth = this.state.img.naturalWidth * this.state.imgScale
        const scaledHeight = this.state.img.naturalHeight * this.state.imgScale

        const canvasOffsetX = (this.state.canvas.width - scaledWidth) / 2 + this.state.imgOffsetX
        const canvasOffsetY = (this.state.canvas.height - scaledHeight) / 2 + this.state.imgOffsetY

        const localCanvasLeft = currentState.left - canvasOffsetX
        const localCanvasTop = currentState.top - canvasOffsetY
        const localCanvasRight = localCanvasLeft + currentState.width
        const localCanvasBottom = localCanvasTop + currentState.height

        matchingItems.forEach(item => {
          item.bsdata.forEach(marker => {
            const scaledMarkerX = marker.x * this.state.imgScale
            const scaledMarkerY = marker.y * this.state.imgScale

            const isInside = scaledMarkerX >= localCanvasLeft &&
              scaledMarkerX <= localCanvasRight &&
              scaledMarkerY >= localCanvasTop &&
              scaledMarkerY <= localCanvasBottom

            marker.labels = isInside // 根据是否在区域内更新状态
          })
        })
      }

      // 添加圆点
      const controlHandles = []
      const createCircle = (index) => {
        const circle = document.createElement('div')
        circle.style.cssText = `
          width: 10px;
          height: 10px;
          background-color: #ff0000;
          border-radius: 50%;
          position: absolute;
          z-index: 15;
          cursor: pointer;
        `
        circle.setAttribute('data-index', index)
        circle.setAttribute('data-role', 'resize-handle')
        canvasContainer.appendChild(circle)
        return circle
      }

      for (let i = 0; i < 8; i++) {
        const circle = createCircle(i)
        controlHandles.push(circle)
        let isResizing = false

        circle.addEventListener(isTouchDevice ? 'touchstart' : 'mousedown', (e) => {
          e.preventDefault()
          e.stopPropagation() // 防止触发拖动事件
          isResizing = true

          const startX = isTouchDevice ? e.touches[0].clientX : e.clientX
          const startY = isTouchDevice ? e.touches[0].clientY : e.clientY

          const startState = { ...currentState }

          const onResizeMove = (moveEvent) => {
            if (!isResizing) return

            const dx = (isTouchDevice ? moveEvent.touches[0].clientX : moveEvent.clientX) - startX
            const dy = (isTouchDevice ? moveEvent.touches[0].clientY : moveEvent.clientY) - startY

            switch (i) {
              case 0: // 左上角
                currentState.width = startState.width - dx
                currentState.height = startState.height - dy
                currentState.left = startState.left + dx
                currentState.top = startState.top + dy
                break
              case 1: // 顶边中心
                currentState.height = startState.height - dy
                currentState.top = startState.top + dy
                break
              case 2: // 右上角
                currentState.width = startState.width + dx
                currentState.height = startState.height - dy
                currentState.top = startState.top + dy
                break
              case 3: // 左边中心
                currentState.width = startState.width - dx
                currentState.left = startState.left + dx
                break
              case 4: // 右边中心
                currentState.width = startState.width + dx
                break
              case 5: // 左下角
                currentState.width = startState.width - dx
                currentState.height = startState.height + dy
                currentState.left = startState.left + dx
                break
              case 6: // 底边中心
                currentState.height = startState.height + dy
                break
              case 7: // 右下角
                currentState.width = startState.width + dx
                currentState.height = startState.height + dy
                break
            }

            overlayCanvas.style.width = `${currentState.width}px`
            overlayCanvas.style.height = `${currentState.height}px`
            overlayCanvas.style.left = `${currentState.left}px`
            overlayCanvas.style.top = `${currentState.top}px`

            updateControlPoints()
            updateMarkers()
          }

          const stopResize = () => {
            isResizing = false
            window.removeEventListener(isTouchDevice ? 'touchmove' : 'mousemove', onResizeMove)
            window.removeEventListener(isTouchDevice ? 'touchend' : 'mouseup', stopResize)
            this.draw('') // 调整完成后更新画布
          }

          window.addEventListener(isTouchDevice ? 'touchmove' : 'mousemove', onResizeMove)
          window.addEventListener(isTouchDevice ? 'touchend' : 'mouseup', stopResize)
        })
      }

      updateControlPoints() // 初始化控制点位置
      updateMarkers() // 初始化标记点状态
    },
    handleCancelst() {
      this.visiblest = false
    },
    handleBeforeOk(done) {
      if (!this.formModel.userText) {
        Message.error('请输入答案')
        return
      }
      done()
    },
    enableDrawingMode() {
      this.currentMode = 'drawing'
      this.currentCursorStyle = 'crosshair'
    },
    enableTextMode() {
      this.currentMode = 'text'
      this.currentCursorStyle = 'text'
    },
    startDrawing(event) {
      if (this.currentMode !== 'drawing' && !this.isEraserMode) return
      this.isDrawing = true
      this.draws(event)
    },
    stopDrawing() {
      this.isDrawing = false
      this.overlayContext.beginPath()

      const MAX_HISTORY = 20 // 最大历史记录长度

      const addHistoryState = () => {
        const canvas = document.getElementById('overlayCanvas')
        const currentState = this.overlayContext.getImageData(0, 0, canvas.width, canvas.height)

        // 如果超出最大长度，移除最早的记录
        if (this.canvasHistory.length >= MAX_HISTORY) {
          this.canvasHistory.shift()
        }
        this.canvasHistory.push(currentState)
      }

      // 保存当前状态到历史记录
      addHistoryState()
    },
    draws(event) {
      event.preventDefault()
      if (!this.isDrawing || !this.overlayContext) return

      const rect = document.getElementById('overlayCanvas').getBoundingClientRect()

      let x, y

      // 判断是否是触摸事件
      if (event.touches && event.touches.length > 0) {
        x = event.touches[0].clientX - rect.left
        y = event.touches[0].clientY - rect.top
      } else {
        x = event.clientX - rect.left
        y = event.clientY - rect.top
      }

      if (this.isEraserMode) {
        // 如果是橡皮擦模式，擦除线段
        this.erase(x, y)
      } else {
        // 否则是绘制模式
        this.overlayContext.lineWidth = this.brushSize
        this.overlayContext.lineCap = 'round'
        this.overlayContext.strokeStyle = this.brushColor

        this.overlayContext.lineTo(x, y)
        this.overlayContext.stroke()
        this.overlayContext.beginPath()
        this.overlayContext.moveTo(x, y)
      }
    },
    erase(x, y, tolerance = 10) {
      const canvas = document.getElementById('overlayCanvas')

      // 获取画布数据
      const imageData = this.overlayContext.getImageData(0, 0, canvas.width, canvas.height)
      const data = imageData.data

      // 获取擦除区域的像素数据
      const eraseRadius = this.brushSize + tolerance // 扩大半径以确保擦除范围足够

      // 循环遍历每个像素
      for (let i = 0; i < data.length; i += 4) {
        const px = (i / 4) % canvas.width
        const py = Math.floor(i / 4 / canvas.width)
        const dx = px - x
        const dy = py - y

        // 计算当前像素点到鼠标点的距离
        if (Math.sqrt(dx * dx + dy * dy) < eraseRadius) {
          data[i] = 255 // R
          data[i + 1] = 255 // G
          data[i + 2] = 255 // B
          data[i + 3] = 0 // A (透明度)
        }
      }

      // 更新画布
      this.overlayContext.putImageData(imageData, 0, 0)
    },
    redrawCanvas() {
      const canvas = document.getElementById('overlayCanvas')
      if (canvas) {
        this.overlayContext.clearRect(0, 0, canvas.width, canvas.height)
      }

      if (this.canvasHistory.length > 0) {
        // 恢复最后的画布状态
        const lastState = this.canvasHistory[this.canvasHistory.length - 1]
        this.overlayContext.putImageData(lastState, 0, 0)
      }
    },
    undo() {
      if (this.canvasHistory.length > 0) {
        // 保存当前状态到重做栈
        const currentState = this.overlayContext.getImageData(0, 0, this.$refs.overlayCanvas.width, this.$refs.overlayCanvas.height)
        this.redoHistory.push(currentState)
        
        // 弹出最近的状态
        const lastState = this.canvasHistory.pop()
        
        // 重绘画布
        this.$nextTick(() => {
          this.overlayContext.putImageData(lastState, 0, 0)
        })
      }
    },
    redo() {
      if (this.redoHistory.length > 0) {
        // 保存当前状态到撤销栈
        const currentState = this.overlayContext.getImageData(0, 0, this.$refs.overlayCanvas.width, this.$refs.overlayCanvas.height)
        this.canvasHistory.push(currentState)
        
        // 获取最近的还原状态
        const lastUndoState = this.redoHistory.pop()
        
        // 重绘画布
        this.$nextTick(() => {
          this.overlayContext.putImageData(lastUndoState, 0, 0)
        })
      }
    },
    toggleEraser() {
      this.isEraserMode = !this.isEraserMode
      this.brushColor = this.isEraserMode ? '#ffffff' : '#ff0000'
    },
    showTextInput(event) {
      if (this.currentMode != 'text') return

      const rect = document.getElementById('overlayCanvas').getBoundingClientRect()
      const x = event.clientX - rect.left
      const y = event.clientY - rect.top

      // 设置输入框的位置
      this.inputStyle = {
        position: 'absolute',
        left: `${event.clientX - 10}px`,
        top: `${event.clientY - 65}px`
      }
      this.customText = '' // 清空输入框内容
      this.showInput = true // 显示输入框

      // 使用 nextTick 确保输入框显示后立即获得焦点
      this.$nextTick(() => {
        const inputElement = document.querySelector('.text-input')
        if (inputElement) {
          inputElement.focus() // 设置焦点
        }
      })
    },
    addTextMarker(text, x, y) {
      if (!this.overlayContext) return

      this.overlayContext.font = '20px Arial'
      this.overlayContext.fillStyle = 'red'
      this.overlayContext.fillText(text, x, y)
    },
    addTextMarkerOnBlur() {
      if (this.customText) {
        this.addTextMarker(
          this.customText,
          parseFloat(this.inputStyle.left),
          parseFloat(this.inputStyle.top)
        )
      }
      this.showInput = false
    },
    addTextMarkerOnEnter(event) {
      if (event.key === 'Enter' && this.customText) {
        this.addTextMarker(
          this.customText,
          parseFloat(this.inputStyle.left),
          parseFloat(this.inputStyle.top)
        )
        this.showInput = false
      }
    },
    handleInputBlur() {
      this.isInputActive = false
      this.addTextMarkerOnBlur()
    },
    downloadImage() {
      this.currentMode = 'download'
      const myCanvas = document.getElementById('myCanvas')
      const overlayCanvas = document.getElementById('overlayCanvas')

      const combinedCanvas = document.createElement('canvas')
      combinedCanvas.width = this.hbwidth
      combinedCanvas.height = this.hbheight
      const ctx = combinedCanvas.getContext('2d', {
        willReadFrequently: true
      })
      // 设置背景颜色为黑色
      ctx.fillStyle = 'black'
      ctx.fillRect(0, 0, combinedCanvas.width, combinedCanvas.height)
      // 绘制原始画布的内容
      ctx.drawImage(myCanvas, 0, 0)
      // 绘制标记画布的内容
      ctx.drawImage(overlayCanvas, 0, 0)

      try {
        // 将合成的画布转换为数据URL
        const imageDataURL = combinedCanvas.toDataURL('image/png')
        // 创建下载链接并触发下载
        const link = document.createElement('a')
        link.href = imageDataURL
        link.download = 'combined_image.png'
        document.body.appendChild(link)
        link.click()
        document.body.removeChild(link)
      } catch (error) {
        console.error('Error exporting canvas: ', error)
      }
    },
    clearOverlay() {
      this.currentMode = 'delel'
      const overlayCanvas = document.getElementById('overlayCanvas')
      if (overlayCanvas) {
        const overlayContext = overlayCanvas.getContext('2d', {
          willReadFrequently: true
        })
        overlayContext.clearRect(0, 0, overlayCanvas.width, overlayCanvas.height)
      }
    },
    handleSearch(query) {
   
      this.optionsselect = []
      this.state.markers.forEach((item) => {
        item.bsdata.forEach((items) => {
          if (items.text.toLowerCase().includes(query.toLowerCase())) {
            this.optionsselect.push({
              markingPointsId: items.markingPointsId,
              text: items.text
            })
          }
        })
      })
    },
    changeselect(e) {
   
      this.state.markers.forEach((item) => {
        item.bsdata.forEach((items) => {
          if (items.markingPointsId == e) {
            let firstPart = item.medicineAtlasImgId.split(',')[0]
            this.state.hoveredMarker = items
            this.tagdcom(Number(firstPart), '搜索')
          }
        })
      })
    },
    changecsd() {
      console.log('当前全选了')
      this.state.markers.forEach((item) => {
        item.bsdata.forEach((items) => {
          items.flag = this.allflag
        })
      })

      this.anatomicStructure.forEach((jg) => {
        jg.flag = this.allflag
      })
      this.saveMarkers()
      this.draw('')
    }
  }
}
</script>

<style scoped>
  .overlayCanvastooitems {
    background: #409eff;
  }
  .text-input-container {
    /* 输入框的容器样式 */
    z-index: 99;
  }

  .text-input {
    padding: 5px;
    border: 1px solid #ccc;
  }
  #overlayCanvas {
    position: absolute;
    top: 0;
    left: 0;
    z-index: 2; /* 画板层 */
  }
  .bjbox {
    width: 100%;
    height: 172px;
  }
  .bjbox img {
    width: 100%;
    height: 172px;
  }
  .mainboxgj {
    display: flex;
    width: 100%;
    height: 100%;
  }
  .maintopbox {
    width: 100%;
    /* height: 45px; */
    height: 4.5%;
    background: linear-gradient(180deg, #504f5d 0%, #212227 100%);
    display: flex;
    justify-content: center;
    align-items: center;
    overflow: hidden;
    position: relative;
  }
  .mainbottombox {
    width: 100%;
    height: 95.5%;
    display: flex;
  }
  .mainbottomboxleft {
    display: flex;
    flex-direction: column;
    width: 82.5%;
    height: 100%;
    overflow: hidden;
  }
  .mainsera {
    position: absolute;
    left: 0px;
    display: flex;
    align-items: center;
    justify-content: center;
  }
  .box {
    margin: 0 auto;
    width: 100%;
    height: 84.5%;
    position: relative;
    overflow: hidden;
  }
  .lboxmain {
    display: flex;
    background-color: #484c56;
    height: 10.5%;
    overflow: hidden;
  }
  .mainsers {
    display: flex;
    align-items: center;
    padding-left: 15px;
    width: 100%;
    height: 5%;
    overflow: hidden;
    color: #333333;
    font-size: 14px;
    background: linear-gradient(180deg, #cfd3d9 0%, #b0b3b8 100%);
  }
  .maintoptitle {
    font-size: 20px;
    color: #ffffff;
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    display: flex;
    justify-content: center;
    align-items: center;
    height: 54px;
  }
  .maintopright {
    display: flex;
    position: absolute;
    right: 354px;
    top: 50%;
    transform: translate(0, -50%);
  }
  .czmainitem {
    cursor: pointer;
    margin: 0 5px;
  }
  .czmainitem img {
    width: 35px;
    height: 36px;
  }
  .gnbocdtop .arco-btn {
    margin: 0;
    /* margin: 5px 10px; */
  }
  .gnbocdtop {
    width: 100%;
    height: 15%;

    border-bottom: 2px solid #5a5a5a;
    display: flex;
    flex-direction: column;
    align-content: center;
    justify-content: center;
    overflow-y: auto;
  }
  .gnbocd {
    width: 100%;
    height: 75%;
    overflow: hidden;
    overflow-y: auto;

    display: flex;
    flex-direction: column;
  }
  .gnbocdname {
    font-size: 20px;
    color: #ffffff;
    padding: 10px;
  }
  .gnbottom {
    height: 90px;
    width: 161px;
    z-index: 9;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
  }
  #canvasContainer {
    position: relative;
  }

  .mentox {
    font-size: 14px;
    color: #fff;
    margin: 6px 0;
  }
  .mentoxs {
    width: 141px;
    height: 40px;
    background: #34343e;
    box-shadow: inset 2px 2px 4px 0px rgba(0, 0, 0, 0.6),
      inset -2px -2px 4px 0px rgba(0, 0, 0, 0.6);
    border-radius: 4px 4px 4px 4px;
    border: 0px solid rgba(255, 255, 255, 0.5);
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
  }
  .mentoxs span {
    font-size: 20px;
    color: #ffffff;
    margin: 0px 5px;
    display: block;
  }
  .mentoxs img {
    width: 31px;
    height: 31px;
  }
  .boxs {
    width: 300px;
    display: flex;
    flex-direction: column;
    align-content: center;
    justify-content: center;
  }
  .zsdkz {
    font-size: 18px;
    color: #ffffff;
    line-height: 30px;
    padding: 5px 10px;
  }
  .boxsitem {
    width: 130px;
    height: 130px;
    margin: 10px 25px;
    background: black;
  }
  .boxsitems {
    text-align: center;
  }

  .bocd {
    /* margin: 10px; */
    /* width: 20%;
     height: 100%; */
    width: 335px;
    height: 905px;
    background: linear-gradient(180deg, #727786 0%, #484c56 1%);
    height: 100%;
    display: flex;
    flex-direction: column;
    overflow-y: auto;
    overflow-x:hidden;
  }
  .mainboxleft {
    width: 100%;
    height: 100%;
    display: flex;
    flex-direction: column;
  }
  .lbox {
    width: 100%;
    height: 100%;
    display: flex;
    overflow: hidden;
    overflow-x: auto;
    white-space: nowrap;
    background-color: #484c56;

    /* border-top: 2px solid #5a5a5a; */
  }

  .lboxitem {
    width: 70px;
    margin: 0px 1px;
    /* height: 70px; */
    cursor: pointer;
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
  }

  .lboxitem img {
    width: 55px;
    height: 55px;
  }

  .msx {
    height: 100px;
    width: 2px;
    background-color: #409eff;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
  }
  .gnbocd::-webkit-scrollbar {
    width: 5px;
    height: 5px;
  }

  .gnbocd::-webkit-scrollbar-track {
    width: 6px;
    background: rgba(#101f1c, 0.1);
    -webkit-border-radius: 2em;
    -moz-border-radius: 2em;
    border-radius: 2em;
  }

  .gnbocd::-webkit-scrollbar-thumb {
    background-color: rgba(133, 138, 148, 0.938);
    background-clip: padding-box;
    min-height: 28px;
    -webkit-border-radius: 2em;
    -moz-border-radius: 2em;
    border-radius: 2em;
    transition: background-color 0.3s;
    cursor: pointer;
  }

  .gnbocd::-webkit-scrollbar-thumb:hover {
    background-color: rgba(144, 147, 153, 0.3);
  }
  .lbox::-webkit-scrollbar {
    width: 5px;
    height: 5px;
  }

  .lbox::-webkit-scrollbar-track {
    width: 6px;
    background: #484c56;
    -webkit-border-radius: 2em;
    -moz-border-radius: 2em;
    border-radius: 2em;
  }

  .lbox::-webkit-scrollbar-thumb {
    background-color: #484c56;
    background-clip: padding-box;
    min-height: 28px;
    -webkit-border-radius: 2em;
    -moz-border-radius: 2em;
    border-radius: 2em;
    transition: background-color 0.3s;
    cursor: pointer;
  }

  .lbox::-webkit-scrollbar-thumb:hover {
    background-color: #484c56;
  }

  .jgdovx {
    margin: 5px 0;
    display: flex;
    justify-content: space-between;
    width: 100%;
  }
  .xugn {
    display: flex;
    /* justify-content: center; */
    align-items: center;
    margin: 5px 0;
    flex-wrap: wrap;
  }
  .xugname {
    width: 80px;
    color: #fff;
    font-size: 16px;
  }
  .xbanner {
    width: 100%;
    font-size: 16px;
    height: 40px;
    background-color: #fff;
    /* line-height: 40px; */
    padding-left: 10px;
    align-content: center;
  }
  .gobackbox {
    width: 80px;
    height: 45px;
    background: #c6ced8;
    display: flex;
    align-items: center;
  }
  .xbannername {
    cursor: pointer;
    font-size: 16px;
    width: 56px;
    height: 28px;
    background: linear-gradient(180deg, #5a6273 0%, #383b42 100%);
    border-radius: 2px 2px 2px 2px;
    text-align: center;
    line-height: 28px;
    margin: 0 auto;
    color: #fff;
  }
  /* 公共类 */
  /* 封装公共按钮类 */
  .tool {
    display: flex;
    justify-content: center;
    align-items: center;
  }
  .tool img.active {
    cursor: pointer;
    display: none;
  }

  .tool:hover img.normal,
  .tool.active img.normal {
    display: none;
  }

  .tool:hover img.active,
  .tool.active img.active {
    display: block;
  }
  .gnboxmain {
    padding: 0 15px;
  }
  .gnboxitem {
    height: 40px;
    background: #24292d;
    border-radius: 4px 4px 4px 4px;
    display: flex;
    align-items: center;
    color: #fff;
    padding: 0 12px;
    margin: 10px 0;
    font-size: 16px;
  }
  .zsbox {
    width: 20%;
    height: 100%;
    background: linear-gradient(180deg, #727786 0%, #484c56 1%);
    display: flex;
    flex-direction: column;
    position: fixed;
    top: 0px;
    right: 0px;
    z-index: 9999;
  }

  .zsbot {
    height: 90%;
    overflow-y: auto;
  }

  .zsclose {
    position: absolute;
    right: 20px;
    cursor: pointer;
  }

  .jpan {
    background-color: #424548;
    border-radius: 4px;
    /* padding: 10px 28px; */
    cursor: pointer;
    width: 108px;
    height: 38px;
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
    margin: 5px 7px;
    text-align: center;
  }
  .jpanitem {
    width: 70%;
    color: #fff;
    text-wrap: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .jpan:hover {
    background-color: #409eff;
    border-radius: 4px;
    max-width: 108px;
  }
  .jpanac {
    background-color: #409eff;
    border-radius: 4px;
    max-width: 108px;
  }
  .overlayCanvastool {
    position: absolute;
    top: 10px;
    right: 100px;
    z-index: 999;
    width: 600px;
    height: 70px;
    background-color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
  }
  .overlayCanvastooitem {
    width: 50px;
    font-size: 30px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
  }
  .startbox {
    width: 90px;
    height: 37px;
    background: linear-gradient(180deg, #f4f4f4 0%, #a2a2a2 100%);
    border-radius: 4px 4px 4px 4px;
    border: 1px solid #000000;
    font-weight: bold;
    font-size: 16px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    margin: 0 5px;
  }
  .startboxs {
    color: #fff;
    margin: 0px 10px;
  }
  .mentname {
    width: 100%;
    height: 53px !important;
    box-shadow: 0px 1px 0px 0px rgba(255, 255, 255, 0.5);
    border-radius: 0px 0px 0px 0px;
    border-bottom: 1px solid #232429;
    padding: 11px 15px;
    display: flex;
    align-items: center;
    color: #fff;
    justify-content: space-between;
    font-size: 18px;
  }
  .menttitle img {
    width: 13px;
    height: 15px;
    margin: 0px 1px;
  }
  .mentright img {
    width: 29px;
    height: 34px;
    margin-top: 7px;
  }
  .mentbjbox {
    display: flex;
    flex-direction: column;
    padding: 10px 15px;
    box-shadow: 0px 1px 0px 0px rgba(255, 255, 255, 0.5);
    border-radius: 0px 0px 0px 0px;
    border-bottom: 1px solid #232429;
  }
  .mentbjtitle {
    color: #ffffff;
    font-size: 18px;
    margin: 10px 0;
  }
  .mentbjtiem {
    width: 291px;
    height: 46px;
    background: #3d4147;
    border-radius: 4px 4px 4px 4px;
    border: 1px solid #5c616d;
    margin: 10px auto;
    display: flex;
    align-items: center;
    justify-content: center;
  }
  .mentsxbox {
    width: 260px;
    min-height: 46px;
    background: #3d4147;
    border-radius: 4px 4px 4px 4px;
    border: 1px solid #5c616d;
    margin: 10px auto;
    display: flex;
    flex-direction: column;
    padding: 15px;
  }
  .mentsxtitle {
    color: #c8c8d2;
    font-size: 16px;
    margin-bottom: 10px;
  }
  .mentbjtiems {
    color: #c8c8d2;
    font-size: 16px;
    align-items: center;
    padding: 0px 10px;
  }
  .mentsxtitembox {
    width: 100%;
    display: flex;
    flex-wrap: wrap;
  }
  .mentsxitems {
    background: linear-gradient(180deg, #ffffff 0%, #c4c4ca 100%);
    color: #000000;
    width: 60px;
    height: 33px;
    border-radius: 4px 4px 4px 4px;
    text-align: center;
    line-height: 33px;
    font-size: 14px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    padding: 0px 10px;
    margin: 5px 3px;
    cursor: pointer;
  }
  .mentsxitem {
    width: 60px;
    height: 33px;
    background: linear-gradient(180deg, #cacad1 0%, #9898a2 100%);
    border-radius: 4px 4px 4px 4px;
    text-align: center;
    line-height: 33px;
    font-size: 14px;
    color: #666666;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    padding: 0px 10px;
    margin: 5px 3px;
    cursor: pointer;
  }
  .mentsxitem:nth-child(3) {
    margin-right: 0px;
  }
  .mentbjtiem .arco-switch {
    background: linear-gradient(160deg, #a7a7a7 0%, #fdfdfd 100%);
    box-shadow: 0px 4px 4px 0px rgba(0, 0, 0, 0.25);
    border-radius: 20px;
  }
  .mentbjtiem .arco-switch-checked {
    background: linear-gradient(180deg, #8cc2ed 0%, #2f7ebd 100%);
    box-shadow: 0px 4px 4px 0px rgba(0, 0, 0, 0.25);
  }
  .mentbjacitem {
    display: flex;
    align-items: center;
    justify-content: center;
  }
  .mentbjacitemtool {
    margin: 0px 6px;
  }
  .mentbjacitemtool img {
    width: 35px;
    height: 35px;
  }
  .colorts {
    position: absolute;
    z-index: 999;
    width: 35px;
    opacity: 0;
  }
  .hbcbox {
    width: 80px;
    height: 105px;
    background: #808080;
    border-radius: 10px 10px 10px 10px;
    position: absolute;
    top: 40px;
    right: -25px;
    display: flex;
    align-items: center;
    flex-direction: column;
    padding: 10px 0px;
    overflow: hidden;
  }

  .hbcitem {
    width: 50px;
    height: 0px;
    border-radius: 4px;
    margin: 5px 0;
  }
  .hbcbox :first-child {
    margin-top: 0px;
  }
  .clseo {
    width: 30px !important;
    height: 30px !important;
    cursor: pointer;
  }
  .sbodyd {
    position: absolute;
    width: 100%;
    height: 100%;
    top: 0;
  }

  .loader-container {
    text-align: center;
    width: 100%;
    height: 100%;
    background-color: rgba(0, 0, 0, 0.9);
    position: fixed;
    top: 0px;
    left: 0px;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-direction: column;
    z-index: 99;
  }
  .loader {
    border: 8px solid #f3f3f3;
    border-top: 8px solid #3498db;
    border-radius: 50%;
    width: 50px;
    height: 50px;
    animation: spin 1s linear infinite;
    margin: 20px auto;
  }
  @keyframes spin {
    0% {
      transform: rotate(0deg);
    }

    100% {
      transform: rotate(360deg);
    }
  }

  .pd {
    font-family: Arial, sans-serif;
    color: #fff;
    font-size: 16px;
    margin-top: 10px;
  }
  /* 滚动条美化 */
  .beautifulScroll::-webkit-scrollbar {
    width: 5px;
    height: 5px;
    background: rgba(0, 0, 0, 0);
    border-radius: 5px;
  }

  .beautifulScroll::-webkit-scrollbar-track {
    background: rgba(0, 0, 0, 0);
    border-radius: 5px;
  }

  .beautifulScroll::-webkit-scrollbar-thumb {
    border-radius: 5px;
    background: #666666;
  }
</style>
